<script setup lang="ts">
import { ref, reactive, computed, watch, watchEffect, toRefs, onMounted, onUnmounted } from 'vue'

// 导航状态
const activeLevel = ref<number>(1)
const setActiveLevel = (level: number) => {
  activeLevel.value = level
}

// 关卡1: ref 示例
const hp = ref(100)
const attacking = ref(false)
const attack = () => {
  attacking.value = true
  setTimeout(() => {
    hp.value -= 20
    attacking.value = false
  }, 500)
}

// 关卡2: reactive 示例
interface Hero {
  name: string
  level: number
  skills: string[]
}

const hero = reactive<Hero>({
  name: 'Vue 法师',
  level: 1,
  skills: ['火球术']
})

const { name, level } = toRefs(hero)

const levelUp = () => {
  level.value++
  if (level.value === 3) hero.skills.push('冰冻术')
}

// 关卡3: computed 示例
const price = ref(25)
const quantity = ref(2)
const discount = ref(0.8)

const total = computed<number>(() => {
  return price.value * quantity.value * discount.value
})

const add = () => quantity.value++

// 关卡4: watch & watchEffect 示例
const id = ref(1)
const data = ref<any>(null)
const loadData = async () => {
  try {
    // 模拟API调用
    console.log(`加载ID为 ${id.value} 的数据`)
    // 实际项目中可以使用真实的API
    // const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id.value}`)
    // data.value = await res.json()
    data.value = { id: id.value, title: `示例任务 ${id.value}`, completed: false }
  } catch (error) {
    console.error('加载数据失败:', error)
  }
}

watch(id, async (newId, oldId) => {
  console.log(`ID 从 ${oldId} → ${newId}`)
  await loadData()
}, { immediate: true })

const x = ref(0)
const y = ref(0)
const updatePosition = () => {
  // 这个效果会在页面上通过按钮触发
}

watchEffect(() => {
  console.log(`角色坐标：(${x.value}, ${y.value})`)
})

// 关卡7作业1: 摄氏↔华氏转换器
const celsius = ref<number>(0)
const fahrenheit = computed<string>(() => {
  return ((celsius.value * 9/5) + 32).toFixed(2)
})

const fahrenheitInput = ref<number>(32)
const celsiusFromFahrenheit = computed<string>(() => {
  return ((fahrenheitInput.value - 32) * 5/9).toFixed(2)
})

// 关卡7作业2: 待办列表
interface Todo {
  id: number
  text: string
  completed: boolean
}

const todos = reactive<Todo[]>([
  { id: 1, text: '学习Vue3', completed: false },
  { id: 2, text: '掌握响应式', completed: false },
  { id: 3, text: '构建项目', completed: false }
])

const newTodoText = ref('')
const uncompletedCount = computed(() => {
  return todos.filter(todo => !todo.completed).length
})

const addTodo = () => {
  if (newTodoText.value.trim()) {
    todos.push({
      id: Date.now(),
      text: newTodoText.value,
      completed: false
    })
    newTodoText.value = ''
  }
}

// 关卡7作业3: 鼠标位置监听
const mouseX = ref(0)
const mouseY = ref(0)

const handleMouseMove = (event: MouseEvent) => {
  mouseX.value = event.clientX
  mouseY.value = event.clientY
}

onMounted(() => {
  window.addEventListener('mousemove', handleMouseMove)
})

onUnmounted(() => {
  window.removeEventListener('mousemove', handleMouseMove)
})
</script>

<template>
  <div class="app">
    <h1>Vue3 响应式学习 - 交互式示例</h1>
    
    <!-- 导航菜单 -->
    <nav class="nav-menu">
      <button 
        v-for="i in 7" 
        :key="i"
        @click="setActiveLevel(i)"
        :class="{ active: activeLevel === i }"
      >
        关卡 {{ i }}
      </button>
      <button 
        @click="setActiveLevel(8)"
        :class="{ active: activeLevel === 8 }"
      >
        关卡7作业
      </button>
    </nav>

    <!-- 关卡1: ref 示例 -->
    <div v-show="activeLevel === 1" class="level-content">
      <h2>关卡 1: ref - 魔法存钱罐</h2>
      <p>让基本类型变成响应式数据</p>
      
      <div class="demo">
        <h3>勇者血量：{{ hp }}</h3>
        <button @click="attack" :disabled="attacking" class="btn">
          {{ attacking ? '攻击中...' : '发起攻击' }}
        </button>
      </div>
    </div>

    <!-- 关卡2: reactive 示例 -->
    <div v-show="activeLevel === 2" class="level-content">
      <h2>关卡 2: reactive - 响应式大别墅</h2>
      <p>让对象/数组的所有属性都变成响应式</p>
      
      <div class="demo">
        <h3>{{ name }} Lv.{{ level }}</h3>
        <p>技能列表：{{ hero.skills.join('、') }}</p>
        <button @click="levelUp" class="btn">打怪升级</button>
      </div>
    </div>

    <!-- 关卡3: computed 示例 -->
    <div v-show="activeLevel === 3" class="level-content">
      <h2>关卡 3: computed - 自动奶茶机</h2>
      <p>根据已有数据自动计算，带缓存功能</p>
      
      <div class="demo">
        <p>单价：{{ price }} × 数量：{{ quantity }} × 折扣：{{ discount }}</p>
        <h4>应付：{{ total.toFixed(2) }} 元</h4>
        <button @click="add" class="btn">再来一杯</button>
      </div>
    </div>

    <!-- 关卡4: watch & watchEffect 示例 -->
    <div v-show="activeLevel === 4" class="level-content">
      <h2>关卡 4: watch & watchEffect - 侦察兵</h2>
      <p>监听数据变化，执行副作用操作</p>
      
      <div class="demo">
        <h3>watch 示例</h3>
        <p>当前ID: {{ id }}</p>
        <button @click="id++" class="btn">下一个ID</button>
        <p v-if="data">数据: {{ JSON.stringify(data) }}</p>
        
        <h3>watchEffect 示例</h3>
        <p>坐标: ({{ x }}, {{ y }})</p>
        <button @click="x++; y++" class="btn">移动角色</button>
        <p>打开控制台查看日志输出</p>
      </div>
    </div>

    <!-- 关卡5: TypeScript 类型支持 -->
    <div v-show="activeLevel === 5" class="level-content">
      <h2>关卡 5: TypeScript 类型推断</h2>
      <p>使用泛型让代码更安全、智能</p>
      
      <div class="demo">
        <pre><code>{{ `// 正确的类型注解
const score = ref<number>(98)

// 错误示例 - 类型不匹配
// const wrongScore = ref<string>(98) // TypeScript 会立即报错

// 接口定义
interface User {
  id: number
  name: string
}

// 类型化的 reactive
const user = reactive<User>({
  id: 1,
  name: 'Vue 学习者'
})` }}</code></pre>
      </div>
    </div>

    <!-- 关卡6: 常见问题 -->
    <div v-show="activeLevel === 6" class="level-content">
      <h2>关卡 6: 常见掉坑题</h2>
      
      <div class="demo">
        <h3>Q1 为什么 const { count } = ref(0) 丢失响应？</h3>
        <p>A: 解构的是基本值，脱离 ref 包裹；正确用 const { count } = toRefs(reactive({ count: 0 }))。</p>
        
        <h3>Q2 直接给 reactive 数组 push 新对象，会响应吗？</h3>
        <p>A: 会！reactive 数组方法被代理，放心 push。</p>
        
        <h3>Q3 在定时器里修改 ref，视图会更新吗？</h3>
        <p>A: 会！Vue3 代理不受"异步限制"困扰，无需 $nextTick。</p>
      </div>
    </div>

    <!-- 关卡7: 总结 -->
    <div v-show="activeLevel === 7" class="level-content">
      <h2>关卡 7: 响应式系统总结</h2>
      
      <div class="demo">
        <h3>核心API对比</h3>
        <table border="1" cellpadding="10">
          <thead>
            <tr>
              <th>API</th>
              <th>用途</th>
              <th>特点</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>ref</td>
              <td>基本类型响应式</td>
              <td>需要 .value 访问/修改</td>
            </tr>
            <tr>
              <td>reactive</td>
              <td>对象/数组响应式</td>
              <td>自动代理所有属性</td>
            </tr>
            <tr>
              <td>computed</td>
              <td>计算属性</td>
              <td>缓存结果，只读</td>
            </tr>
            <tr>
              <td>watch</td>
              <td>监听变化</td>
              <td>精确监听，有新旧值</td>
            </tr>
            <tr>
              <td>watchEffect</td>
              <td>自动副作用</td>
              <td>自动收集依赖</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <!-- 关卡7作业 -->
    <div v-show="activeLevel === 8" class="level-content">
      <h2>关卡 7 选做作业实现</h2>
      
      <!-- 作业1: 温度转换器 -->
      <div class="demo homework">
        <h3>作业1: 摄氏 ↔ 华氏温度转换器</h3>
        <div>
          <label>
            摄氏度: 
            <input type="number" v-model.number="celsius" />
          </label>
          <p>华氏度: {{ fahrenheit }} ℉</p>
        </div>
        <div>
          <label>
            华氏度: 
            <input type="number" v-model.number="fahrenheitInput" />
          </label>
          <p>摄氏度: {{ celsiusFromFahrenheit }} ℃</p>
        </div>
      </div>

      <!-- 作业2: 待办列表 -->
      <div class="demo homework">
        <h3>作业2: 待办列表</h3>
        <p>剩余未完成: {{ uncompletedCount }}</p>
        <div>
          <input type="text" v-model="newTodoText" placeholder="输入新任务" />
          <button @click="addTodo" class="btn">添加</button>
        </div>
        <ul>
          <li v-for="todo in todos" :key="todo.id">
            <input type="checkbox" v-model="todo.completed" />
            <span :class="{ completed: todo.completed }">{{ todo.text }}</span>
          </li>
        </ul>
      </div>

      <!-- 作业3: 鼠标位置 -->
      <div class="demo homework">
        <h3>作业3: 鼠标位置实时显示</h3>
        <p>鼠标X坐标: {{ mouseX }}</p>
        <p>鼠标Y坐标: {{ mouseY }}</p>
        <p>移动鼠标查看坐标变化</p>
      </div>
    </div>
  </div>
</template>

<style scoped>
.app {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

h1 {
  text-align: center;
  color: #42b883;
}

.nav-menu {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 30px;
  justify-content: center;
}

.nav-menu button {
  padding: 8px 16px;
  border: 1px solid #42b883;
  background-color: white;
  color: #42b883;
  cursor: pointer;
  border-radius: 4px;
  transition: all 0.3s;
}

.nav-menu button:hover {
  background-color: #42b883;
  color: white;
}

.nav-menu button.active {
  background-color: #42b883;
  color: white;
}

.level-content {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.demo {
  background-color: white;
  padding: 20px;
  border-radius: 4px;
  margin-top: 20px;
}

.btn {
  background-color: #42b883;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  transition: background-color 0.3s;
}

.btn:hover:not(:disabled) {
  background-color: #3aa876;
}

.btn:disabled {
  background-color: #ccc;
  cursor: not-allowed;
}

.homework {
  margin-bottom: 30px;
  border: 1px solid #ddd;
}

.completed {
  text-decoration: line-through;
  color: #888;
}

code {
  background-color: #f0f0f0;
  padding: 2px 4px;
  border-radius: 3px;
}

pre {
  background-color: #f0f0f0;
  padding: 15px;
  border-radius: 4px;
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
}

th, td {
  border: 1px solid #ddd;
  padding: 8px;
  text-align: left;
}

th {
  background-color: #f2f2f2;
}
</style>
